package com.plan.base.intercepter;

import com.alibaba.fastjson2.JSON;
import com.plan.base.config.property.AppProperty;
import com.plan.base.constant.BaseCode;
import com.plan.base.constant.Constant;
import com.plan.base.entity.Result;
import com.plan.base.limiter.UserRateLimiter;
import com.plan.base.util.DateUtil;
import com.plan.controller.user.response.UserVO;
import com.plan.entity.user.UserPackage;
import com.plan.enums.UserLevelEnum;
import com.plan.service.uesr.AuthManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 拦截器
 *
 * @author zcl
 */
@Slf4j
@Component
public class UserInterceptor implements HandlerInterceptor {
    @Resource
    private AuthManager authManager;
    @Resource
    private AppProperty appProperty;
    private final UserRateLimiter userRateLimiter = new UserRateLimiter(10, TimeUnit.SECONDS, 100);


    /**
     * 判断是否有用户登录信息，没有则拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
        String token = request.getHeader(Constant.TOKEN_NAME);

        Result<String> result;
        if (token != null) {
            if (authManager.isExpiration(token)) {
                result = Result.fail(BaseCode.INVALID_TOKEN);
            } else {
                UserVO vo = authManager.getUserForToken(token);
                if (!userRateLimiter.isAllowed(vo.getId())) {
                    // 限流
                    result = Result.fail(BaseCode.USER_REQ_LIMIT);
                } else {
                    request.setAttribute(Constant.USER_KEY, vo);
                    // 游客不让访问
                    if (vo.getLevel() == UserLevelEnum.NORMAL.getLevel()) {
                        // 游客试用期结束后就不能访问了
                        if (new Date().after(DateUtil.addDays(vo.getCreateTime(), appProperty.getFreeDay()))) {
                            // 后续还要做IP黑名单：微信tokenId要记录
                            result = Result.fail(BaseCode.ACCESS_DENIED);
                        } else {
                            return true;
                        }
                    } else if (vo.getLevel() == UserLevelEnum.SVIP.getLevel()) {
                        // 超级VIP所有功能直接访问
                        return true;
                    } else {
                        // 普通VIP要校验是否购买
                        String uri = request.getRequestURI();

                        Integer packageId = authManager.getPackageId(uri);
                        List<UserPackage> packages = vo.getPackages();
                        if (packageId != null && packages != null && packages.size() > 0) {
                            for (UserPackage p : packages) {
                                if (p.getPackageId().compareTo(packageId) == 0) {
                                    if (p.getExpireTime().after(new Date())) {
                                        return true;
                                    }
                                }
                            }
                        }
//                    result = Result.fail(BaseCode.FORBIDDEN_BUSY_FIRST, request.getLocale());
                        // 暂进没有资源包
                        return true;
                    }
                }
            }
        } else {
            result = Result.fail(BaseCode.INVALID_TOKEN, request.getLocale());
        }

        // 写回错误信息
        result.setMsg(Result.getMessages(result.getCode(), request.getLocale()));
        response.setCharacterEncoding("utf-8");
        response.getWriter().write(JSON.toJSONString(result));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) throws Exception {

    }


}